<template>
  <view class="cinema-seat-select" :style="[cinemaSeatStyle]">
    <!-- 缩略图 -->
    <cinemaMinLayout ref="minSeatLayout" :col-count="colCount" :seat-infos="seatInfos" :change="change" :scale="scale" :rect="rect" :move-area-height="moveAreaHeight"></cinemaMinLayout>
    <!-- 调试面板 -->
    <!-- <view class="dubeg-wrap">
      <text>change x: {{ change.x }}, y: {{ change.y }}</text>
      <text>scale x: {{ scale.x }}, y: {{ scale.y }}, scale: {{ scale.scale }}</text>
    </view> -->
    <view class="seat-wrap">
      <view v-if="loading" class="loading-wrap">
        <zm-loading size="28rpx" text-color="#999999" text-size="28rpx">座位加载中...</zm-loading>
      </view>
      <view class="seat-content" :style="[seatContentStyle]">
        <view class="seat-yaxis" :style="[seatYaxisStyle]">
          <view class="track" :style="[seatYaxisTrackStyle]">
            <view v-for="(number, index) in row" :key="index" class="number" :style="[seatYaxisNumberStyle]">{{ number }}</view>
          </view>
        </view>
        <movable-area scale-area class="movable-area">
          <movable-view
            class="movable-view"
            direction="all"
            scale
            :damping="30"
            :scale-min="scaleMin"
            :scale-max="scaleMax"
            :scale-value="scaleValue"
            :x="center.x"
            :y="center.y"
            @scale="handleMovableScale"
            @change="handleMovableChange"
          >
            <view v-if="data.planInfo" class="header-wrap" :style="[headerWrapStyle]">
              <image class="line" :src="useImage('/zuimei-film-oss/1.0.0/seat/line.png')" mode="scaleToFill" />
              <text class="text-666 font-20">{{ data.planInfo.hallName }}</text>
            </view>
            <view v-if="seatInfos.length" class="seat-grid" :style="[seatGridStyle]">
              <view v-for="(rowItem, rowIndex) in seatInfos" :key="rowIndex" class="seat-row" :style="[seatRowStyle]">
                <view v-for="(colItem, colIndex) in rowItem" :key="colIndex" class="seat-col" :style="[seatColStyle(colItem)]" @click="handleClickCol(rowIndex, colIndex, colItem)">
                  <template v-if="colItem.seatNo">
                    <image v-if="colItem._select" class="seat-icon" :src="colItem['_select-icon']" mode="scaleToFill" />
                    <image v-else class="seat-icon" :src="colItem._icon" mode="scaleToFill" />
                  </template>
                </view>
              </view>
            </view>
          </movable-view>
        </movable-area>
      </view>
    </view>
  </view>
</template>

<script>
import hook from "@/mixins/hook"
import weixin from "@/mixins/weixin"
import cinemaMinLayout from "../cinema-mini-layout/index.vue"
import { baseImageUrl } from "@/config"
const STATUS_UNCHECK = 0 // 未选
const STATUS_CHECKED = 1 // 已选
export default {
  name: "seat-select",
  components: { cinemaMinLayout },
  mixins: [hook, weixin],
  props: {
    data: {
      type: Object,
      default: () => ({ planInfo: {} })
    },
    moveAreaHeight: {
      type: Number,
      default: 300
    },
    seatIconOptions: {
      type: Object,
      default: () => {}
    },
    planKey: {
      type: [String, Number],
      default: ""
    },
    limit: {
      type: [String, Number],
      default: ""
    }
  },
  data() {
    return {
      loading: false,
      rect: {},
      allSeats: [], // 扁平化所有的座位，转一维数组
      selectSeats: [], // 已选择的座位
      filmScreenHeight: 58,
      old: { x: 0, y: 0, scale: 1 },
      change: { x: 0, y: 0 },
      scale: { x: 0, y: 0, scale: 1 },
      disableClick: false,
      rowCount: 0,
      colCount: 0,
      gridSize: 18,
      gridGap: 4,
      scaleMax: 1.8, // uniapp最大缩放值10
      scaleMin: 1, // uniapp最小值0.5
      scaleValue: 1,
      center: {
        x: 0,
        y: 0
      },
      row: [],
      planInfo: {},
      seatInfos: [],
      seatIcons: {} // 座位图标
    }
  },
  computed: {
    // 容器高度
    cinemaSeatStyle() {
      const style = {}
      style.height = this.moveAreaHeight + "px"
      return style
    },
    // 影院名称高度
    headerWrapStyle() {
      const style = {}
      style.height = this.filmScreenHeight + "px"
      return style
    },
    seatContentStyle() {
      const style = {}
      style.display = this.loading ? "none" : "flex"
      return style
    },
    // 网格样式
    seatGridStyle() {
      const style = {}
      style.gap = this.gridGap + "px"
      style.margin = "0 auto"
      return style
    },
    // 网格行样式
    seatRowStyle() {
      const style = {}
      style.gap = this.gridGap + "px"
      style.marginBottom = this.gridGap + "px"
      style.height = this.gridSize + "px"
      style.gridTemplateColumns = `repeat(${this.colCount}, ${this.gridSize}px)`
      return style
    },
    // 网格列样式
    seatColStyle() {
      return (col) => {
        const style = {}
        style.gap = this.gridSize + "px"
        style.height = this.gridSize + "px"
        if (["L"].includes(col.seatType)) {
          style["grid-column"] = `span 2`
        }
        if (!col.seatNo) {
          style.visibility = "hidden"
        }
        if (col.seatType === "R") {
          style.display = "none"
        }
        return style
      }
    },
    //  y轴移动距离
    seatYaxisStyle() {
      const style = {}
      style.top = this.change.y + this.filmScreenHeight * this.scale.scale + "px"
      return style
    },
    // 网格左侧Y轴样式
    seatYaxisTrackStyle() {
      const style = {}
      style.gap = this.gridGap * this.scale.scale + "px"
      return style
    },
    // 网格左侧Y轴样式
    seatYaxisNumberStyle() {
      const style = {}
      style.height = this.gridSize * this.scale.scale + "px"
      return style
    }
  },
  watch: {
    data: {
      handler(val) {
        if (uni.$check.isNoEmpty(val)) {
          this.handleInit()
        }
      },
      deep: true,
      immediate: true
    }
  },
  methods: {
    //获取关联座位（情侣座）,用于判断选择座位数是否超过可选数
    getRelationSeat(vale, key = "seatPieceNo") {
      return this.allSeats.filter((i) => i[key] === vale)
    },
    // 点击座位
    handleClickCol(rowIndex, colIndex, col) {
      if (this.disableClick) return
      if (col.seatFlag === 1) return
      if (col.seatState === -1) return
      // 可选择时，判断最大座位数限制
      const ableSeat = this.limit - this.selectSeats.length // 剩余可选座位数
      const relationLen = this.getRelationSeat(col.seatPieceNo).length
      switch (col.seatState) {
        case STATUS_UNCHECK:
          if (ableSeat < relationLen) {
            if (relationLen === 1) {
              uni.$toast(`最多只能选择${this.limit}个座位`)
            } else {
              uni.$toast(`本次剩余可选座位不足${relationLen}个`)
            }
            return
          }
          this.seatInfos[rowIndex][colIndex]._select = true
          this.seatInfos[rowIndex][colIndex].seatState = STATUS_CHECKED
          if (this.seatInfos[rowIndex][colIndex].seatType == "L" && this.seatInfos[rowIndex][colIndex + 1]) {
            this.seatInfos[rowIndex][colIndex + 1]._select = true
            this.seatInfos[rowIndex][colIndex + 1].seatState = STATUS_CHECKED
          }
          break

        case STATUS_CHECKED:
          this.cancelSeat(col.seatNo)
          break
      }

      this.handleConfirmSelect()
    },
    // 处理选座
    handleConfirmSelect() {
      const list = []
      this.seatInfos.forEach((item) => {
        item.forEach((subItem) => {
          if (subItem._select) {
            list.push(subItem)
          }
        })
      })

      this.selectSeats = list
      this.$refs.minSeatLayout.show()
      this.$emit("select", list)
    },
    // 重置座位
    resetSeat() {
      this.selectSeats.map((item) => {
        console.log(item)
        this.cancelSeat(item.seatNo, false)
      })
      this.selectSeats = []
    },
    // 取消座位
    cancelSeat(seatNo, emit = true) {
      const index = this.allSeats.findIndex((item) => {
        return item.seatNo == seatNo
      })
      const row = +this.allSeats[index].graphRow
      const col = +this.allSeats[index].graphCol
      this.seatInfos[row][col]._select = false
      this.seatInfos[row][col].seatState = STATUS_UNCHECK
      if (this.allSeats[index].seatType == "R") {
        this.seatInfos[row][col - 1]._select = false
        this.seatInfos[row][col - 1].seatState = STATUS_UNCHECK
      } else if (this.allSeats[index].seatType == "L") {
        this.seatInfos[row][col + 1]._select = false
        this.seatInfos[row][col + 1].seatState = STATUS_UNCHECK
      }
      emit && this.handleConfirmSelect()
    },
    // 缩放到合适的座位大小
    handleScaleSeat(scale) {
      this.scale.scale = scale
      this.scaleValue = scale
    },
    flatSetlist() {
      this.allSeats = []
      const _seatInfos = uni.$clone(this.seatInfos)
      for (let len = _seatInfos.length; len--; ) {
        const cInfo = _seatInfos[len]
        for (let clen = cInfo.length; clen--; ) {
          this.allSeats.push(cInfo[clen])
        }
      }
    },
    handleInit() {
      this.handleScaleSeat(1)
      this.row = uni.$clone(this.data.row)
      this.planInfo = uni.$clone(this.data.planInfo)
      // 生成区域图标
      if (this.planInfo.areas?.length) {
        this.planInfo.areas.forEach((item, index) => {
          this.seatIcons[item.areaId] = `${baseImageUrl}/zuimei-film-oss/1.0.0/seat/type-${index}.png`
        })
      } else {
        this.seatIcons[0] = `${baseImageUrl}/zuimei-film-oss/1.0.0/seat/type-${0}.png`
      }
      const seatInfos = uni.$clone(this.data.seatInfos)
      this.seatInfos = seatInfos.map((item) => {
        return item.map((subItem) => {
          const data = subItem
          data._select = false
          // 不可售图标
          if (data.seatState == -1 && data.seatFlag == 1) {
            data._icon = this.seatIconOptions["disable"]
          }
          // 单人图标
          else if (data.seatType == "N" && data.seatState == -1 && data.seatFlag !== 1) {
            data._icon = this.seatIconOptions["sold"]
            data["_select-icon"] = this.seatIconOptions["select"]
          }
          // 双人图标
          else if (data.seatType == "L" || data.seatType == "R") {
            data._icon = this.seatIconOptions[data.seatState == -1 ? "sold-double" : "double"]
            data["_select-icon"] = this.seatIconOptions["select-double"]
          }
          // 区域图标
          else if (data.seatType == "N") {
            data._icon = this.seatIcons[subItem.areaId] || this.seatIcons[0]
            data["_select-icon"] = this.seatIconOptions["select"]
          }
          return data
        })
      })
      this.selectSeats = []
      this.flatSetlist()
      this.resize()
    },
    resize(loading = true) {
      this.loading = loading
      //  行数
      this.rowCount = this.seatInfos.length
      //  列数
      this.colCount = Math.max(...this.seatInfos.map((s) => s.length))

      if (loading) {
        this.$nextTick(() => {
          this.loading = false
          this.setSeatCenter()
        })
      } else {
        this.reset()
      }
    },
    reset() {
      // 重置左侧坐标
      this.handleScaleSeat(1)
      this.scale.scale = 1
      this.change.y = 0
      this.scale.y = this.old.y
      this.scale.y = 0
      this.center.y = this.old.y
      this.center.y = 0
    },
    setSeatCenter() {
      setTimeout(async () => {
        this.rect = await this.useRect(".movable-view")
        const contentRect = await this.useRect(".seat-content")
        if (this.rect && contentRect) {
          this.center.x = -((this.rect.width - contentRect.width) / 2)
          // this.center.y = -((this.rect.height - contentRect.height) / 2)
        }
      }, 500)
    },

    // 缩放
    handleMovableScale(e) {
      this.disableClick = true
      this.old.scale = e.detail.scale
      this.scale.x = e.detail.x
      this.scale.y = e.detail.y
      this.scale.scale = e.detail.scale
      this.change.y = e.detail.y
      this.old.x = e.detail.x
      this.old.y = e.detail.y
      uni.$debounce(() => {
        this.disableClick = false
      }, 150)
    },
    // 移动
    handleMovableChange(e) {
      this.disableClick = true
      this.change.x = e.detail.x - this.scale.x
      this.change.y = e.detail.y
      this.old.x = e.detail.x
      this.old.y = e.detail.y
      this.$refs.minSeatLayout.show()
      uni.$debounce(() => {
        this.disableClick = false
      }, 150)
    },
    // 锁座前判断（是否隔空选座）
    judgeChoose() {
      const selectedSeatList = this.selectSeats
      for (let i = 0; i < selectedSeatList.length; i++) {
        const _item = selectedSeatList[i]
        const _rowIndex = +_item.graphRow
        const _row = this.seatInfos[_rowIndex]
        const _col = +_item.graphCol // 当前列
        // 座位状态 -1不可售  0-未售，1-售出，2 置空位 3-预订，4-选中，7-已锁定,9-验收   -2 当前选座
        const leftOne = _row[_col - 1]
        const leftTwo = _row[_col - 2]
        const rightOne = _row[_col + 1]
        const rightTwo = _row[_col + 2]
        if (!leftOne || (leftOne.seatState !== STATUS_UNCHECK && leftOne.seatState !== STATUS_CHECKED)) {
          // 左边靠墙
        } else if (!rightOne || (rightOne.seatState !== STATUS_UNCHECK && rightOne.seatState !== STATUS_CHECKED)) {
          // 右边靠墙
        } else if (
          leftOne &&
          leftOne.seatState === STATUS_UNCHECK &&
          leftTwo &&
          leftTwo.seatState === STATUS_UNCHECK &&
          rightOne &&
          rightOne.seatState === STATUS_UNCHECK &&
          rightTwo &&
          rightTwo.seatState === STATUS_UNCHECK
        ) {
          // 左右必须都有两个位置
        } else {
          if (leftOne && leftOne.seatState === STATUS_UNCHECK && (!leftTwo || leftTwo.seatState !== STATUS_UNCHECK)) {
            // 左边空一格
            for (var j = _col + 1; j < _row.length; j++) {
              const right = _row[j]
              if (!right) {
                break
              }
              if (right.seatState !== STATUS_UNCHECK && right.seatState !== STATUS_CHECKED) {
                break
              }
              if (right.seatState === STATUS_UNCHECK) {
                // uni.$toast("请勿隔空选座")
                return false
              }
            }
          }

          if (rightOne && rightOne.seatState === STATUS_UNCHECK && (!rightTwo || rightTwo.seatState !== STATUS_UNCHECK)) {
            // 右边空一格
            for (var k = _col - 1; k >= STATUS_UNCHECK; k--) {
              const left = _row[k]
              if (!left) {
                break
              }
              if (left.seatState !== STATUS_UNCHECK && left.seatState !== STATUS_CHECKED) {
                break
              }
              if (left.seatState === STATUS_UNCHECK) {
                // uni.$toast("请勿隔空选座")
                return false
              }
            }
          }
        }
      }
      return true
    }
  }
}
</script>

<style lang="scss" scoped>
.cinema-seat-select {
  display: flex;
  position: relative;
  align-items: center;
  flex-direction: column;

  .dubeg-wrap {
    top: 60rpx;
    right: 0;
    z-index: 10;
    display: flex;
    padding: 12rpx;
    color: #1dff87;
    position: fixed;
    flex-direction: column;
    background: rgba(0, 0, 0, 0.2);
  }
  .header-wrap {
    display: flex;
    align-items: center;
    flex-direction: column;
    transition: all 0.1s ease;
    .line {
      width: 392rpx;
      height: 26rpx;
    }
  }
  .seat-wrap {
    flex: 1;
    width: 100%;
    display: flex;
    // margin-bottom: 36rpx;
    flex-direction: column;
    .loading-wrap {
      top: 50%;
      left: 50%;
      position: absolute;
      transform: translate(-50%, -50%);
    }
    .seat-content {
      flex: 1;
      width: 100%;
      display: flex;
      overflow: hidden;
      position: relative;
    }
    .seat-yaxis {
      top: 0;
      // margin-top: 40px;
      z-index: 1;
      left: 24rpx;
      width: 32rpx;
      color: #fff;
      font-size: 20rpx;
      position: absolute;
      border-radius: 16rpx;
      pointer-events: none;
      background: rgba(0, 0, 0, 0.2);
      .track {
        display: flex;
        align-items: center;
        flex-direction: column;
        transition: all 0.1s ease;

        .number {
          display: flex;
          align-items: center;
        }
      }
    }
    .movable-area {
      width: 100%;
      height: 100%;
      min-height: 200px;
      .movable-view {
        height: auto;
        width: auto;
        padding-bottom: 50px;
        margin-bottom: 30rpx;
        transform-origin: 0px 0px;
        /* #ifdef MP-TOUTIAO */
        transform-origin: center;
        /* #endif */
      }
    }
  }

  .seat-grid {
    height: 100%;
    position: relative;
    padding: 0 40px;
    &::before {
      content: "";
      position: absolute;
      width: 1rpx;
      height: calc(100% + 20px);
      left: 50%;
      margin-top: -10px;
      top: 0;
      bottom: 0;
      border-left: dashed 1rpx rgb(197, 196, 196);
      z-index: -1;
    }
    &::after {
      content: "";
      position: absolute;
      width: 100%;
      height: 1rpx;
      top: 50%;
      left: 0;
      right: 0;
      border-top: dashed 1rpx rgb(197, 196, 196);
      z-index: -1;
    }
    .seat-row {
      display: grid;
      .seat-col {
        display: flex;
        &.is-hide {
          visibility: hidden;
        }
        .seat-icon {
          width: 100%;
          height: 100%;
        }
      }
    }
  }
}
</style>
